package com.uvnos4j.matilda.system.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.uvnos4j.matilda.commons.dto.PageParam;
import com.uvnos4j.matilda.commons.dto.QueryParam;
import com.uvnos4j.matilda.commons.exception.ServiceException;
import com.uvnos4j.matilda.commons.utils.MpUtil;
import com.uvnos4j.matilda.system.domain.SysDict;
import com.uvnos4j.matilda.system.error.SystemError;
import com.uvnos4j.matilda.system.mapper.SysDictMapper;
import com.uvnos4j.matilda.system.service.SysDictService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * 字典 Service 实现
 * <p>
 * Description:字典 Service 实现
 * </p>
 *
 * @author Guo.wl
 * @version v1.0.0
 * @see com.uvnos4j.matilda.system.service.impl
 * @since 2020-08-31 23:17:49
 */
@Service
@Transactional(readOnly = true)
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {

    @Override
    public IPage<SysDict> findPage(QueryParam param, PageParam pageParam, String orderBy) {
        String id = param.getStringValue("id");
        String type = param.getStringValue("type");

        LambdaQueryWrapper<SysDict> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StrUtil.isNotBlank(id), SysDict::getId, id);
        lqw.like(StrUtil.isNotBlank(type), SysDict::getType, type);

        Page<SysDict> page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize());
        page.setOrders(MpUtil.getOrderList(orderBy));

        return baseMapper.selectPage(page, lqw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(SysDict sysDict) {
        if (hasSameDictAtType(sysDict.getType(), sysDict.getText(), null)) {
            throw new ServiceException(SystemError.DICT_REPEAT_AT_SAME_TYPE);
        }
        return baseMapper.insert(sysDict) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(SysDict sysDict) {
        if (hasSameDictAtType(sysDict.getType(), sysDict.getText(), sysDict.getId())) {
            throw new ServiceException(SystemError.DICT_REPEAT_AT_SAME_TYPE);
        }
        SysDict before = baseMapper.selectById(sysDict.getId());
        if (before == null) {
            throw new ServiceException(SystemError.DICT_NO_EXIST);
        }
        return baseMapper.updateById(sysDict) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        return baseMapper.deleteBatchIds(idList) > 0;
    }

    @Override
    public void export(QueryParam param, PageParam pageParam, String orderBy, String fileDest) {
        IPage<SysDict> pageResult = findPage(param, pageParam, orderBy);

        ExcelWriter writer = ExcelUtil.getWriter(fileDest);
        writer.write(pageResult.getRecords(), true);
        writer.close();
    }

    @Override
    public List<SysDict> findListByTypes(String[] types) {
        LambdaQueryWrapper<SysDict> lqw = new LambdaQueryWrapper<>();
        lqw.in(SysDict::getType, types);
        return baseMapper.selectList(lqw);
    }

    private boolean hasSameDictAtType(String type, String text, Long id) {
        LambdaQueryWrapper<SysDict> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysDict::getType, type).eq(SysDict::getText, text).ne(id != null, SysDict::getId, id);
        Integer count = baseMapper.selectCount(lqw);
        return count > 0;
    }

}